/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.inspur.edp.cef.generator.coreGenerator.base.accessorgen.method;

import com.inspur.edp.caf.generator.baseInfo.ParameterInfo;
import com.inspur.edp.caf.generator.baseInfo.TypeInfo;
import com.inspur.edp.caf.generator.method.ClassMethodGenerator;
import com.inspur.edp.caf.generator.utils.ExpressionUtils;
import com.inspur.edp.cef.api.message.CefException;
import com.inspur.edp.cef.core.data.AccessorCollection;
import com.inspur.edp.cef.entity.entity.IEntityDataCollection;
import com.inspur.edp.cef.generator.coreGenerator.base.accessorgen.AccessorClassTypeInfo;
import com.inspur.edp.cef.generator.overall.GeneratorUtil;
import com.inspur.edp.das.commonmodel.IGspCommonObject;
import org.eclipse.jdt.core.dom.*;

import java.util.ArrayList;

public class AccessorCreateAndSetChildCollectionGen extends ClassMethodGenerator
{
	private static final String FormalParName = "childNodeCode";
	private IGspCommonObject commonObject;
	private java.util.Map<String, String> childNodeFields;
	private AccessorClassTypeInfo accessorTypeInfo;
	public AccessorCreateAndSetChildCollectionGen(IGspCommonObject commonObject, java.util.Map<String, String> childNodeFields, AccessorClassTypeInfo accessorTypeInfo)
	{
		this.commonObject = commonObject;
		this.childNodeFields = childNodeFields;
		this.accessorTypeInfo = accessorTypeInfo;
	}
	@Override
	protected String getMethodName()
	{
		return "innerCreateAndSetChildCollection";
	}


	@Override
	protected TypeInfo getReturnType() {
		return new TypeInfo(IEntityDataCollection.class);
	}

	@Override
	protected boolean getIsOverride() {
		return true;
	}

	@Override
	protected ArrayList<Modifier.ModifierKeyword> getAccessModifiers() {
		ArrayList<Modifier.ModifierKeyword> list =new ArrayList<>();
		list.add(Modifier.ModifierKeyword.PUBLIC_KEYWORD);
		return list;
	}

	@Override
	protected ArrayList<ParameterInfo> getParameterCollection() {
		ArrayList<ParameterInfo> list =new ArrayList<>();
		ParameterInfo parameterInfo=new ParameterInfo();
		parameterInfo.setParamName(FormalParName);
		parameterInfo.setParamType(new TypeInfo(String.class.getTypeName()));
		list.add(parameterInfo);
		return list;
	}

	@Override
	protected void doInitialize()
	{
	}

	@Override
	protected Block buildMethodBody() {
		Block block=ast.newBlock();
		addPropertyStatements(block);
		addDefaultThrowStatement(block);
		return block;
	}

	private void addPropertyStatements(Block block) {
		if(commonObject==null)
			return;
		for (IGspCommonObject childObject:commonObject.getContainChildObjects())
		{
			addPropertyIfStatement(block,childObject);
		}
	}

	//if (childNodeCode == "SalesOrderItem")
	private void addPropertyIfStatement(Block block, IGspCommonObject childObject)
	{
		IfStatement ifStatement=ast.newIfStatement();
		addIfExpression(ifStatement,childObject);
		addIfThen(ifStatement,childObject);
		block.statements().add(ifStatement);
	}

	private void addIfExpression(IfStatement ifStatement, IGspCommonObject childObject) {
		MethodInvocation methodInvocation=ast.newMethodInvocation();
		methodInvocation.setExpression(ast.newSimpleName(FormalParName));
		methodInvocation.setName(ast.newSimpleName("equals"));
		methodInvocation.arguments().add(ExpressionUtils.getStringLiteral(ast, childObject.getCode()));
		ifStatement.setExpression(methodInvocation);
	}

	private void addIfThen(IfStatement ifStatement, IGspCommonObject childObject) {
		Block block=ast.newBlock();
		addIfThenDeclaration(block,childObject);
		addIfThenSetParent(block);
		addIfThenAssignItems(block,childObject);
		addIfThenReturn(block,childObject);
		ifStatement.setThenStatement(block);
}

	private void addIfThenDeclaration(Block block, IGspCommonObject childObject) {
		VariableDeclarationFragment variableDeclarationFragment= ast.newVariableDeclarationFragment();
		variableDeclarationFragment.setName(ast.newSimpleName("collection"));

		MethodInvocation newCollectionInvocation = ast.newMethodInvocation();
		newCollectionInvocation.setName(ast.newSimpleName(NewChildCollectionGenerator.getMethodName(childObject)));
		newCollectionInvocation.arguments().add(ast.newNullLiteral());

		variableDeclarationFragment.setInitializer(newCollectionInvocation);

		VariableDeclarationStatement variableDeclarationStatement=ast.newVariableDeclarationStatement(variableDeclarationFragment);
		variableDeclarationStatement.setType(new TypeInfo(AccessorCollection.class).getType(ast));
		block.statements().add(variableDeclarationStatement);
	}

	private  String getChildCollectionTypes(IGspCommonObject childObject)
	{
	return 	accessorTypeInfo.getChildObjAccessorCollectionTypes().get(childObject.getCode()).getFullName();
	}

	private void addIfThenSetParent(Block block)
	{
		MethodInvocation methodInvocation=ast.newMethodInvocation();
		methodInvocation.setName(ast.newSimpleName("setParent"));
		methodInvocation.setExpression(ast.newSimpleName("collection"));
		methodInvocation.arguments().add(ast.newThisExpression());

		block.statements().add(ast.newExpressionStatement(methodInvocation));
	}

	private void addIfThenAssignItems(Block block, IGspCommonObject childObject)
	{
		Assignment assignment=ast.newAssignment();

		assignment.setOperator(Assignment.Operator.ASSIGN);
		assignment.setLeftHandSide(ast.newSimpleName(childNodeFields.get(childObject.getCode())));
		assignment.setRightHandSide(ast.newSimpleName("collection"));
		ExpressionStatement expressionStatement=ast.newExpressionStatement(assignment);
		block.statements().add(expressionStatement);
	}

	private void addIfThenReturn(Block block, IGspCommonObject childObject)
	{
		ReturnStatement returnStatement =ast.newReturnStatement();
		returnStatement.setExpression(ast.newSimpleName(childNodeFields.get(childObject.getCode())));
		block.statements().add(returnStatement);
	}

	private void addDefaultThrowStatement(Block block) {
		addImport(CefException.class.getTypeName());
		ThrowStatement throwStatement= GeneratorUtil.getThrowStatement(ast,null);
//		ClassInstanceCreation classInstanceCreation=ast.newClassInstanceCreation();
//		setExceptionCode.setClassInstanceCreation(classInstanceCreation,ast,"","");
//		classInstanceCreation.setType(new com.inspur.edp.caf.generator.baseInfo.TypeInfo(RuntimeException.class).getType(ast));
//		throwStatement.setExpression(classInstanceCreation);

		block.statements().add(throwStatement);
	}

//	@Override
//	protected Block buildMethodBody()
//	{

//		var propSwitchStatement = SyntaxFactory.SwitchStatement(SyntaxFactory.IdentifierName(FormalParName));

//		for (var prop : propertyInfos)
//		{

//			var childAttr = prop.<ChildAttribute>getCustomAttribute();
//			if (childAttr == null)
//			{
//				continue;
//			}
//			propSwitchStatement = propSwitchStatement.AddSections(getChildPropSection(childAttr));
//		}
//		propSwitchStatement = propSwitchStatement.AddSections(getDefaultSection());
//		return SyntaxFactory.Block(SyntaxFactory.<StatementSyntax>SingletonList(propSwitchStatement));
//	}
//
//
//	private SwitchSectionSyntax getChildPropSection(ChildAttribute childAttr)
//	{
//													//SyntaxFactory.Token(SyntaxKind.CommaToken),
//													//SyntaxFactory.Argument(
//													//    SyntaxFactory.ThisExpression())
//		return SyntaxFactory.SwitchSection().WithLabels(SyntaxFactory.<SwitchLabelSyntax>SingletonList(SyntaxFactory.CaseSwitchLabel(SyntaxFactory.LiteralExpression(SyntaxKind.StringLiteralExpression, SyntaxFactory.Literal(childAttr.getObjectCode()))))).WithStatements(SyntaxFactory.List(new StatementSyntax[] { SyntaxFactory.ExpressionStatement(SyntaxFactory.AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, SyntaxFactory.IdentifierName(childNodeFields.get(childAttr.getObjectCode())), SyntaxFactory.ObjectCreationExpression(SyntaxFactory.ParseName(accessorTypeInfo.getChildObjAccessorCollectionTypes().get(childAttr.getObjectCode()).FullName)).WithArgumentList(SyntaxFactory.ArgumentList(SyntaxFactory.<ArgumentSyntax>SeparatedList(new SyntaxNodeOrToken[] { SyntaxFactory.Argument(SyntaxFactory.LiteralExpression(SyntaxKind.NullLiteralExpression)) }))).WithInitializer(SyntaxFactory.InitializerExpression(SyntaxKind.ObjectInitializerExpression, SyntaxFactory.<ExpressionSyntax>SingletonSeparatedList(SyntaxFactory.AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, SyntaxFactory.IdentifierName("Parent"), SyntaxFactory.ThisExpression())))))), SyntaxFactory.ReturnStatement(SyntaxFactory.CastExpression(TypeUtils.getTypeSyntax(IEntityDataCollection.class), SyntaxFactory.IdentifierName(childNodeFields.get(childAttr.getObjectCode())))) }));
//	}
//
//	private SwitchSectionSyntax getDefaultSection()
//	{
//		return SyntaxFactory.SwitchSection().WithLabels(SyntaxFactory.<SwitchLabelSyntax>SingletonList(SyntaxFactory.DefaultSwitchLabel())).WithStatements(SyntaxFactory.<StatementSyntax>SingletonList(SyntaxFactory.ThrowStatement(SyntaxFactory.ObjectCreationExpression(TypeUtils.getTypeSyntax(ArgumentOutOfRangeException.class)).WithArgumentList(SyntaxFactory.ArgumentList()))));
//	}
}
